﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace LaserTubeCuttingMachine.Utilities
{
    public class XMLHelper
    {
        /// <summary>
        /// Read specific nodes from XML file.
        /// </summary>
        /// <typeparam name="T">One node is an object, and its attributes are the object properties. T is the object type.</typeparam>
        /// <param name="name">Node name.</param>
        /// <param name="filename">XML filename including path.</param>
        /// <returns>Object list.</returns>
        /// <exception cref="ArgumentException">When node name and filename is null or white space.</exception>

        public static List<T> ReadObjectsByName<T>(string name, string filename) where T : class
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentException($"'{nameof(name)}' cannot be null or whitespace.", nameof(name));
            }

            if (string.IsNullOrWhiteSpace(filename))
            {
                throw new ArgumentException($"'{nameof(filename)}' cannot be null or whitespace.", nameof(filename));
            }

            List<T> list = new List<T>();
            Type type = typeof(T);

            using FileStream fs = File.OpenRead(filename);

            XmlReaderSettings settings = new XmlReaderSettings
            {
                ConformanceLevel = ConformanceLevel.Document
            };

            using XmlReader reader = XmlReader.Create(fs, settings);
            while (reader.Read())
            {
                if (reader.IsStartElement() && reader.Name == name)
                {
                    T t = Activator.CreateInstance<T>();

                    while (reader.MoveToNextAttribute())
                    {
                        string attr = reader.Name;
                        string value = reader.Value;

                        var property = type.GetProperty(attr);
                        switch (property?.PropertyType.Name)
                        {
                            case "Double":
                                property?.SetValue(t, Convert.ToDouble(value));
                                break;
                            case "Int32":
                                property?.SetValue(t, Convert.ToInt32(value));
                                break;
                            case "Boolean":
                                property?.SetValue(t, Convert.ToBoolean(value));
                                break;
                            default:
                                property?.SetValue(t, value);
                                break;
                        }
                    }

                    list.Add(t);
                }
            }

            return list;
        }
    }
}
